package com.zy.utils;

import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ZYThreadUtils {

    private static final String TAG = "ZYThreadUtils";

    private static final HandlerThread thread = new HandlerThread("handler-test");
    public static Handler mHandler;

    private static int mNextId;

    static {
        thread.start();
        mHandler = new Handler(thread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d(TAG, "消息处理 开始 " + getMessageShow(msg));
                if (msg.arg2 == 1) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Log.d(TAG, "消息处理 结束 " + getMessageShow(msg));

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    showMSGQueue();
                }
            }
        };
    }


    @RequiresApi(api = Build.VERSION_CODES.M)
    public static void addIdleHandler() {  //添加6条空闲消息处理器
        for (int i = 0; i < 6; i++) {
            int finalI = i;
            mHandler.getLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
                @Override
                public boolean queueIdle() {
                    Log.d(TAG, "queueIdle 调用:" + finalI);
                    return true; //保留
                }
            });
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.M)
    public static void addMainIdleHandler() {  //添加6条空闲消息处理器
        for (int i = 0; i < 6; i++) {
            int finalI = i;
            Looper.getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
                @Override
                public boolean queueIdle() {
                    Log.d(TAG, "queueIdle 调用:" + finalI);
                    return true; //保留
                }
            });
        }
    }

    public static void setCommonMsg() {
        int i = mNextId++;
        Message message = Message.obtain();
        message.what = i;
        message.obj = "我是普通消息" + i;
        Log.d(TAG, "发送普通消息:" + i);
        mHandler.sendMessage(message);
    }

    public static void setCommonMsgSleep() {
        int i = mNextId++;
        Message message = Message.obtain();
        message.what = i;
        message.arg2 = 1; //执行过程中睡眠五秒，便于统计队列
        message.obj = "我是普通耗时消息" + i;
        Log.d(TAG, "发送普通耗时消息:" + i);
        mHandler.sendMessage(message);
    }

    public static void sendMessageDelayed() {
        int i = mNextId++;
        Message message = Message.obtain();
        message.what = i;
        message.obj = "我是普通延时消息" + i;
        Log.d(TAG, "发送普通延时消息:" + i);
        mHandler.sendMessageDelayed(message, 5000);
    }

    public static void setAsynchronous() {
        int i = mNextId++;
        Message message = Message.obtain();
        message.what = i;
        message.obj = "我是异步消息" + i;
        message.setAsynchronous(true);
        Log.d(TAG, "发送异步消息:" + i);
        mHandler.sendMessage(message);
    }

    public static int postSyncBarrier() {
        try {
            Method postSyncBarrierMethod = MessageQueue.class.getDeclaredMethod("postSyncBarrier");
            postSyncBarrierMethod.setAccessible(true);
            int token = (int) postSyncBarrierMethod.invoke(thread.getLooper().getQueue());
            Log.d(TAG, "发送同步屏障 token:" + token);
            return token;
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return -1;
    }

    public static void removeSyncBarrier(int token) {
        try {
            Method removeSyncBarrierMethod = MessageQueue.class.getDeclaredMethod("removeSyncBarrier", int.class);
            removeSyncBarrierMethod.setAccessible(true);
            Log.d(TAG, "移除同步屏障 token:" + token);
            removeSyncBarrierMethod.invoke(thread.getLooper().getQueue(), token);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private static String getMessageShow(Message message) {
        return "isAsynchronous:" + message.isAsynchronous() + " " + System.identityHashCode(message) + " " + message;
    }

    public static void showMSGQueue() {
        try {
            Field mMessagesField = MessageQueue.class.getDeclaredField("mMessages");
            mMessagesField.setAccessible(true);
            Message head = (Message) mMessagesField.get(thread.getLooper().getQueue());
            Message curMSG = head;
            Log.d(TAG, "\nshowMSGQueue -- start --------------------------");
            int size = 0;
            List<String> msgDesList = new ArrayList<>();
            while (curMSG != null) {
                msgDesList.add((++size) + " " + getMessageShow(curMSG));
                curMSG = getNext(curMSG);
            }
            Log.d(TAG, "队列长度:" + size);
            for (String des : msgDesList) {
                Log.d(TAG, des);
            }
            Log.d(TAG, "showMSGQueue -- end --------------------------\n");

        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static Message getNext(Message msg) {
        if (msg == null) {
            return null;
        }

        try {
            Field nextField = Message.class.getDeclaredField("next");
            nextField.setAccessible(true);
            return (Message) nextField.get(msg);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            Log.e(TAG, "getNext" + e);

        }
        return null;
    }

    //--------------------------------------------------------
}
